import 'package:family_expense/features/bank_card/models/bank.dart';
import 'package:family_expense/features/bank_card/models/bank_card.dart';
import 'package:family_expense/features/bank_card/services/bank_card_service.dart';
import 'package:family_expense/features/bank_card/services/bank_service.dart';
import 'package:family_expense/features/bank_card/widgets/bank_shared.dart';
import 'package:flutter/material.dart';
import 'package:my_flutter_core/my_flutter_core.dart';
import 'package:sprintf/sprintf.dart';

/// Why not use [Provider] because the [initState] will be called only once.
/// If use [StatelessWidget] the [_needToRefreshBankCardHome] will be reset to false sometimes.
///
/// IMPORTANT!!!
/// Please be noted. Be very careful with [FutureBuilder] in the [build] method.
/// Each time [setState] method triggers [build] method will cause [FutreBuilder] run again.
/// This behavior might NOT be the one you expect.
///
/// [AsyncMemoizer] in 'package:async/async.dart'; can help on this scenario. It can make sure async function only will be called once.
/// https://stackoverflow.com/questions/59353637/flutter-populate-form-with-async-data
/// final AsyncMemoizer _memoizer = AsyncMemoizer();
/// final dnController = new TextEditingController();
///
/// // Only fetch data once and set its text value
/// // Setting it here ensures that the value doesn't go back
/// // to the stored user value on every widget rebuild
// ignore: unintended_html_in_doc_comment
/// Future<dynamic> getUser() {
///
///   return this._memoizer.runOnce(() async {
///
///     final user = await locator<AppAuth>().currentUser();
///
///     dnController.text = user.displayName;
///
///     return user;
///   });
/// }
///
/// // Set it as the future
/// return FutureBuilder(
///   future: getUser(),
///   ...
///
/// TextFormField(controller: dnController)
class BankCardInfo extends StatefulWidget {
  const BankCardInfo(this.id, {super.key});

  final String id;

  @override
  State<BankCardInfo> createState() => _BankCardInfoState();
}

class _BankCardInfoState extends State<BankCardInfo> {
  final BankService _bankService = BankService();
  final BankCardService _bankCardService = BankCardService();

  // Current authenticated user.
  User? _user;

  BankCard? _bankCard;
  List<Bank>? _banks;
  bool? _dataUpdated = false;

  @override
  void initState() {
    super.initState();

    _getCurrentUser();
    _queryBankCardInfo();
  }

  @override
  Widget build(BuildContext context) {
    return PopScope(
      canPop: false,
      onPopInvokedWithResult: _onPopInvokedWithResult,
      child: Scaffold(
        appBar: _buildAppBar(),
        body: _user?.isAccountGroupAdmin == true
            ? _buildEditableBody(_bankCard)
            : _buildBody(_bankCard),
      ),
    );
  }

  /// Builds app bar.
  PreferredSizeWidget _buildAppBar() {
    return AppBar(
      title: _buildAppBarTitle(),
      actions: <Widget>[
        if (_user?.isAccountGroupAdmin == true)
          IconButton(
            icon: const Icon(Icons.delete),
            tooltip: '删除',
            onPressed: _delete,
          ),
      ],
    );
  }

  /// Generates the user detail item list for view only.
  Widget _buildBody(BankCard? bankCard) {
    if (bankCard == null) {
      return const MyPageTopCenterLoadingIndicator();
    }

    return ListView(
      children: [
        Padding(
          padding: const EdgeInsets.symmetric(vertical: 10.0),
          child: ListTile(
            title: const Text('银行'),
            trailing: ClipOval(
              child: Hero(
                tag: bankCard.id!,
                transitionOnUserGestures: true,
                child: BankLogo(bankCard.bank!),
              ),
            ),
          ),
        ),
        ListTile(title: const Text('名称'), trailing: Text(bankCard.name!)),
        if (bankCard.isCreditCard!)
          Column(
            children: [
              ListTile(
                title: const Text('账单日'),
                trailing: Text(
                  _getCreditCardStatementDateDescription(
                    bankCard.statementDate,
                  )!,
                ),
              ),
              ListTile(
                title: const Text('还款日'),
                trailing: Text(
                  _getCreditCardPaymentDueDateDescription(
                    bankCard.paymentDueDate,
                  )!,
                ),
              ),
            ],
          ),
        ListTile(
          title: const Text('客服号码'),
          trailing: Text(bankCard.customerServiceNumber ?? ''),
        ),
      ],
    );
  }

  /// Generates the user detail item list for admin.
  Widget _buildEditableBody(BankCard? bankCard) {
    if (bankCard == null) {
      return const MyPageTopCenterLoadingIndicator();
    }

    return ListView(
      children: [
        SwitchListTile(
          title: const Text('可用'),
          value: bankCard.enabled!,
          onChanged: (_) {
            if (mounted) {
              // Triggers build.
              setState(() => bankCard.enabled = !bankCard.enabled!);
            }

            // Need to refresh the [BankCardHome] when pops.
            _dataUpdated = true;

            // Updates the data to the server.
            _bankCardService.update(bankCard);
          },
        ),
        const Divider(),
        SwitchListTile(
          title: const Text('信用卡'),
          value: bankCard.isCreditCard!,
          onChanged: (_) {
            if (mounted) {
              // Triggers build.
              setState(() => bankCard.isCreditCard = !bankCard.isCreditCard!);
            }

            // Need to refresh the [BankCardHome] when pops.
            _dataUpdated = true;

            // Updates the data to the server.
            _bankCardService.update(bankCard);
          },
        ),
        Padding(
          padding: const EdgeInsets.symmetric(vertical: 10.0),
          child: SimpleDetailListTile(
            title: const Text('银行'),
            value: ClipOval(
              child: Hero(
                tag: bankCard.id!,
                transitionOnUserGestures: true,
                child: BankLogo(bankCard.bank!),
              ),
            ),
            onTap: () => _showBankModalBottomSheet(bankCard),
          ),
        ),
        SimpleTextDetailListTile(
          title: '名称',
          value: bankCard.name!,
          formTextFieldValidator: FormTextFieldValidator(
            null,
            null,
            maxLength: BankCard.nameMaxLength,
          ),
          onConfirmed: (value) {
            if (mounted) {
              // Triggers build.
              setState(() => bankCard.name = value);
            }

            // Need to refresh the [BankCardHome] when pops.
            _dataUpdated = true;

            // Updates the data to the server.
            _bankCardService.update(bankCard);
          },
        ),
        AnimatedSize(
          duration: const Duration(milliseconds: 200),
          child: Visibility(
            visible: bankCard.isCreditCard!,
            child: Column(
              children: [
                SimpleTextDetailListTile(
                  title: '账单日',
                  value: bankCard.statementDate ?? '',
                  valueDescription: _getCreditCardStatementDateDescription(
                    bankCard.statementDate,
                  ),
                  keyboardType: TextInputType.number,
                  formTextFieldValidator: FormTextFieldValidator(
                    null,
                    null,
                    isRequired: bankCard.isCreditCard,
                    isPositiveNumber: true,
                    maxLength: BankCard.paymentDueDateMaxLength,
                  ),
                  onConfirmed: (value) {
                    if (mounted) {
                      // Triggers build.
                      setState(() => bankCard.statementDate = value);
                    }

                    // Need to refresh the [BankCardHome] when pops.
                    _dataUpdated = true;

                    // Updates the data to the server.
                    _bankCardService.update(bankCard);
                  },
                ),
                SimpleTextDetailListTile(
                  title: '还款日',
                  value: bankCard.paymentDueDate ?? '',
                  valueDescription: _getCreditCardPaymentDueDateDescription(
                    bankCard.paymentDueDate,
                  ),
                  keyboardType: TextInputType.number,
                  formTextFieldValidator: FormTextFieldValidator(
                    null,
                    null,
                    isRequired: bankCard.isCreditCard,
                    isPositiveNumber: true,
                    maxLength: BankCard.paymentDueDateMaxLength,
                  ),
                  onConfirmed: (value) {
                    if (mounted) {
                      // Triggers build.
                      setState(() => bankCard.paymentDueDate = value);
                    }

                    // Updates the data to the server.
                    _bankCardService.update(bankCard);
                  },
                ),
              ],
            ),
          ),
        ),
        SimpleTextDetailListTile(
          title: '客服号码',
          value: bankCard.customerServiceNumber ?? '',
          formTextFieldValidator: FormTextFieldValidator(
            null,
            null,
            isRequired: false,
            maxLength: BankCard.customerServiceNumberMaxLength,
          ),
          onConfirmed: (value) {
            if (mounted) {
              // Triggers build.
              setState(() => bankCard.customerServiceNumber = value);
            }

            // Updates the data to the server.
            _bankCardService.update(bankCard);
          },
        ),
      ],
    );
  }

  /// Builds the app bar title widget to display the different style of titles for debit card and credit card.
  /// Credit card display more info to indicate the statement date range.
  Widget _buildAppBarTitle() {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Text(
          _bankCard != null ? '${_bankCard!.bank!.name}${_bankCard!.name}' : '',
        ),
        Text(
          _bankCard?.isCreditCard == true
              ? BankShared.getCreditCardStatementDateRangeDescription(_bankCard)
              : '储蓄卡',
          style: MyFontStyle.appBarSubtitleStyle,
        ),
      ],
    );
  }

  /// Gets current authenticated user.
  Future<void> _getCurrentUser() async {
    final user = await AuthStateService.instance.currentUser;

    if (mounted) {
      setState(() => _user = user);
    }
  }

  Future<void> _queryBankCardInfo() async {
    final res = await _bankCardService.queryBankCardInfo(widget.id);

    if (mounted) {
      setState(() => _bankCard = res);
    }
  }

  /// Checks the data before popping.
  void _onPopInvokedWithResult(bool didPop, dynamic result) {
    if (didPop) {
      return;
    }

    if (_bankCard!.isCreditCard! &&
        (_bankCard!.statementDate.isNullOrEmpty ||
            _bankCard!.paymentDueDate.isNullOrEmpty)) {
      showToast('请完善信用卡的账单日和还款日');
    } else {
      // Passes the update bank card to previous page for list update.
      NavigatorHelper.pop<bool>(context, _dataUpdated);
    }
  }

  /// Gets the readable description for credit card statementDate.
  ///
  /// '24' means the 24th of current month.
  /// '+3' means the 3rd of next month.
  String? _getCreditCardStatementDateDescription(String? date) {
    if (date.isNullOrEmpty) {
      return '';
    } else {
      return sprintf('每月%s号', [date]);
    }
  }

  /// Gets the readable description for credit card paymentDueDate.
  ///
  /// '24' means the 24th of current month.
  /// '+3' means the 3rd of next month.
  String? _getCreditCardPaymentDueDateDescription(String? date) {
    if (date.isNullOrEmpty) {
      return '';
    } else if (date!.startsWith('+')) {
      return sprintf('下月%s号', [date.replaceFirst('+', '')]);
    } else {
      return sprintf('当月%s号', [date]);
    }
  }

  /// Shows a pick modal for bank selection.
  Future<void> _showBankModalBottomSheet(BankCard bankCard) async {
    // If the bank list is not loaded yet.
    _banks ??= await _bankService.queryAllWithBasicInfo();

    // DO NOT use BuildContext across asynchronous gaps.
    // https://dart-lang.github.io/linter/lints/use_build_context_synchronously.html
    if (mounted) {
      BankShared.showBankModalBottomSheet(context, _banks!, (bank) {
        if (mounted) {
          // Triggers build.
          setState(() => bankCard.bank = bank);
        }

        // Need to refresh the [BankCardHome] when pops.
        _dataUpdated = true;

        // Closes modal.
        NavigatorHelper.pop(context);

        // Updates the data to the server.
        _bankCardService.update(bankCard);
      }, bankCard: bankCard);
    }
  }

  /// Deletes current bank card.
  void _delete() {
    showConfirmDialog(
      context,
      '删除卡片 ${_bankCard!.name}？',
      onConfirm: () async {
        showInProgressOverlay(context);

        // Deletes item on back server.
        final deleted = await _bankCardService.delete(_bankCard!.id!);

        // DO NOT use BuildContext across asynchronous gaps.
        // https://dart-lang.github.io/linter/lints/use_build_context_synchronously.html
        if (mounted) {
          // Closes progress overlay.
          NavigatorHelper.pop(context);
        }

        if (deleted) {
          _dataUpdated = true;

          // DO NOT use BuildContext across asynchronous gaps.
          // https://dart-lang.github.io/linter/lints/use_build_context_synchronously.html
          if (mounted) {
            // Pops detail view and notifies last page.
            NavigatorHelper.pop(context, _dataUpdated);
          }
        } else {
          showToast('卡片 ${_bankCard!.name} 已被使用，不可删除。');
        }
      },
    );
  }
}
